/* Copyright (c) 2022 渝州大数据实验室
 *
 * Lanius is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.yzbdl.lanius.orchestrate.serv.utils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.system.ApplicationHome;

/**
 * 任务实例日志处理工具类
 *
 * @author jinchunzhao@yzbdl.ac.cn
 * @date 2022-04-18 15:51
 */
public class TaskInstanceLogUtil {

    private static final Logger logger = LoggerFactory.getLogger(TaskInstanceLogUtil.class);

    /**
     * 组织文件夹前缀
     */
    private static final String LOG_ORG_PRE = "org_";

    /**
     * 任务编排分组文件夹前缀
     */
    private static final String LOG_TASK_PLAN_GROUP_PRE = "taskPlanGroup_";

    /**
     * 任务编排文件夹前缀
     */
    private static final String LOG_TASK_PLAN_PRE = "taskPlan_";

    /**
     * 任务实例日志文件名前缀
     */
    private static final String LOG_TASK_INSTANCE_PRE = "taskInstance_";

    /**
     * 日志后缀名
     */
    private static final String LOG_SUFFIX = ".txt";

    /**
     * 日志路径前缀
     */
    private static final String LOG_PATH = "task-instance-log";

    /**
     * windows环境路径
     */
    private static final String WINDOWS_TASK_LOG_PATH = "C:\\task\\instance-log\\";

    /**
     * 系统类型：windows
     */
    private static final String SYS_TYPE_WINDOWS = "windows";

    /**
     * 系统类型：linux
     */
    private static final String SYS_TYPE_LINUX = "linux";

    /**
     * 写入日志
     *
     * @param orgId
     *        组织ID
     * @param groupId
     *        任务编排分组ID
     * @param taskId
     *        任务编排ID
     * @param taskInstanceId
     *        任务实例ID
     */
    public static void writerLog(Long orgId, Long groupId, Long taskId, Long taskInstanceId, String log) {

        if (StringUtils.isBlank(log)) {
            return;
        }

        BufferedWriter out = null;
        try {
            File logFile = createLogFile(orgId, groupId, taskId, taskInstanceId);
            // 以文件追加的方式写入日志
            out = new BufferedWriter(new FileWriter(logFile, true));
            out.write(log);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("任务实例日志写入失败", e);
        } finally {
            if (Objects.nonNull(out)) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 获取日志文件绝对路径
     *
     * @param orgId
     *        组织ID
     * @param groupId
     *        任务编排分组ID
     * @param taskId
     *        任务编排ID
     * @param taskInstanceId
     *        任务实例ID
     * @return
     *        日志文件路径
     */
    public static String getLogAbsolutePath(Long orgId, Long groupId, Long taskId, Long taskInstanceId) {
        String logFilePath = getLogFolderPath(orgId, groupId, taskId);
        StringBuilder sb = new StringBuilder(logFilePath);
        sb.append(File.separator);
        sb.append(LOG_TASK_INSTANCE_PRE).append(taskInstanceId).append(LOG_SUFFIX);

        logger.warn("----------日志文件路径----------------：{}", sb.toString());
        return sb.toString();
    }

    /**
     * 写入日志
     *
     * @param orgId
     *        组织ID
     * @param groupId
     *        任务编排分组ID
     * @param taskId
     *        任务编排ID
     */
    public static void deleteLog(Long orgId, Long groupId, Long taskId) throws Exception{
        String logFilePath = getLogFolderPath(orgId, groupId, taskId);
        File file = new File(logFilePath);
        // 删文件
        deleteFile(file);

        // 删目录
        file.delete();
    }

    /**
     * 删除文件夹下的所有文件
     *
     * @param file
     *        文件
     * @throws Exception
     *         异常
     */
    private static void deleteFile(File file)throws Exception{
        File[] files = file.listFiles();
        assert files != null;
        for (File fileTemp : files) {
            if (fileTemp.isDirectory()){
                deleteFile(file);
            }
            fileTemp.delete();
        }
    }

    /**
     * 创建日志文件
     *
     * @param orgId
     *        组织ID
     * @param groupId
     *        任务编排分组ID
     * @param taskId
     *        任务编排ID
     * @param taskInstanceId
     *        任务实例ID
     * @return 日志File对象
     * @throws IOException
     *         IO异常
     */
    private static File createLogFile(Long orgId, Long groupId, Long taskId, Long taskInstanceId) throws IOException {
        String logAbsolutePath = getLogAbsolutePath(orgId, groupId, taskId, taskInstanceId);

        File file = new File(logAbsolutePath);

        if (!file.exists()) {
            String logFolderPath = getLogFolderPath(orgId, groupId, taskId);
            File fileFolder = new File(logFolderPath);
            if (!fileFolder.exists()) {
                fileFolder.mkdirs();
            }
            file.createNewFile();
        }
        return file;
    }

    /**
     * 获取日志文件目录路径
     *
     * @param orgId
     *        组织ID
     * @param groupId
     *        任务编排分组ID
     * @param taskId
     *        任务编排ID
     * @return
     *        日志文件路径
     */
    private static String getLogFolderPath(Long orgId, Long groupId, Long taskId) {
        String logPathPre = null;

        Integer systemType = getSystemType();
        if (Objects.equals(systemType, SystemTypeEnum.WINDOWS.ordinal())) {
            logPathPre = WINDOWS_TASK_LOG_PATH;
        } else {
            logPathPre = getJarPath() + LOG_PATH + File.separator;
        }

        StringBuilder sb = new StringBuilder(logPathPre);
        sb.append(LOG_ORG_PRE).append(orgId).append(File.separator).append(LOG_TASK_PLAN_GROUP_PRE).append(groupId)
            .append(File.separator).append(LOG_TASK_PLAN_PRE).append(taskId);
        return sb.toString();
    }

    /**
     * 获取系统类型
     *
     * @return
     *        系统类型
     */
    private static Integer getSystemType() {
        String os = System.getProperty("os.name");
        if (Objects.nonNull(os) && os.toLowerCase().startsWith(SYS_TYPE_WINDOWS)) {
            return SystemTypeEnum.WINDOWS.ordinal();
        } else if (Objects.nonNull(os) && os.toLowerCase().startsWith(SYS_TYPE_LINUX)) {
            return SystemTypeEnum.LINUX.ordinal();
        }
        return SystemTypeEnum.WINDOWS.ordinal();
    }

    /**
     * 获取jar包所在的目录
     *
     * @return
     *        jar包所在的目录
     */
    private static String getJarPath() {
        ApplicationHome applicationHome = new ApplicationHome(TaskInstanceLogUtil.class);
        File jarF = applicationHome.getSource();
        return jarF.getParentFile().toString() + File.separator;
    }

    /**
     * 系统类型
     */
    private enum SystemTypeEnum {
        /**
         * 系统类型
         */
        WINDOWS, LINUX;
    }

}
